package logging

import (
	"os"
	"time"

	"go.uber.org/zap"
	"go.uber.org/zap/zapcore"
)

// newDefaultProductionLog configures a custom log that is
// intended for use by default if no other log is specified
// in a config. It writes to stderr, uses the console encoder,
// and enables INFO-level logs and higher.
func newDefaultProductionLog() *zap.Logger {
	encCfg := zap.NewProductionEncoderConfig()
	// if interactive terminal, make output more human-readable by default
	encCfg.EncodeTime = func(ts time.Time, encoder zapcore.PrimitiveArrayEncoder) {
		encoder.AppendString(ts.Format("2006/01/02 15:04:05.000"))
	}
	encCfg.EncodeLevel = zapcore.CapitalColorLevelEncoder
	enc := zapcore.NewConsoleEncoder(encCfg)
	core := zapcore.NewCore(enc, zapcore.Lock(os.Stdout), zap.NewAtomicLevelAt(zap.DebugLevel))

	return zap.New(core)

}

// Logger returns the current default logger.
func Logger() *zap.Logger {
	return defaultLogger
}

func SetLogFile(errorPath, debugPath string) error {
	highPriority := zap.LevelEnablerFunc(func(lvl zapcore.Level) bool {
		return lvl >= zapcore.WarnLevel
	})
	lowPriority := zap.LevelEnablerFunc(func(lvl zapcore.Level) bool {
		return lvl < zapcore.WarnLevel
	})

	encCfg := zap.NewProductionEncoderConfig()
	// if interactive terminal, make output more human-readable by default
	encCfg.EncodeTime = func(ts time.Time, encoder zapcore.PrimitiveArrayEncoder) {
		encoder.AppendString(ts.Format("2006/01/02 15:04:05.000"))
	}
	encCfg.EncodeLevel = zapcore.CapitalLevelEncoder
	enc := zapcore.NewConsoleEncoder(encCfg)

	errFile, err := os.OpenFile(errorPath, os.O_WRONLY|os.O_APPEND|os.O_CREATE, 0644)
	if err != nil {
		return err
	}
	debugFile, err := os.OpenFile(debugPath, os.O_WRONLY|os.O_APPEND|os.O_CREATE, 0644)
	if err != nil {
		return err
	}

	core := zapcore.NewTee(
		defaultLogger.Core(),
		zapcore.NewCore(enc, zapcore.AddSync(errFile), highPriority),
		zapcore.NewCore(enc, zapcore.AddSync(debugFile), lowPriority),
	)
	defaultLogger = zap.New(core)
	return nil
}

var (
	defaultLogger = newDefaultProductionLog()
)
